/**
 ******************************************************************************
 * @file    plic.c
 * @author  hyseim software Team
 * @date    12-Mar-2024
 * @brief   
 ******************************************************************************
 * @attention
 * 
 * Copyright (c) 2020 Hyseim. Co., Ltd.
 * All rights reserved.
 * 
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 * 
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "plic.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/


/**
 * @brief Deinitializes the PLIC peripheral registers to their default reset values.
 */
void PLIC_Deinit()
{
    // Disable all interrupts.
    for (uint32_t i = 0; i < (PLIC_NUM_INTERRUPTS >> 2); i++)
    {
        PLIC->ENABLE[0][i] = 0;
    }

    // Set all priorities to 0.
    for (uint32_t i = 0; i < PLIC_NUM_INTERRUPTS; i++)
    {
        PLIC->PRIORITY[i] = 0;
    }
    
    // Set the threshold to 0.
    PLIC->context[0].THRESHOLD = 0;
}

/**
 * @brief set the priority of an interrupt
 * @param [in] irq
 * @param [in] priority
 */
void PLIC_SetPriority(uint32_t irq, uint32_t priority)
{
    PLIC->PRIORITY[irq] = priority;
}

/**
 * @brief get the priority of an interrupt
 * @param [in] irq
 * @return uint32_t 
 */
uint32_t PLIC_GetPriority(uint32_t irq)
{
    return PLIC->PRIORITY[irq];
}

/**
 * @brief get the pending status of an interrupt
 * @param [in] irq
 * @return uint32_t 
 */
uint32_t PLIC_GetPendingStatus(uint32_t irq)
{
    return PLIC->PENDING[irq >> 5] & (1 << (irq & 0x1F));
}

/**
 * @brief enable an interrupt
 * @param [in] irq
 */
void PLIC_EnableIRQ(uint32_t irq)
{
    PLIC->ENABLE[0][irq >> 5] |= (1 << (irq & 0x1F));
}

/**
 * @brief disable an interrupt
 * @param [in] irq
 */
void PLIC_DisableIRQ(uint32_t irq)
{
    PLIC->ENABLE[0][irq >> 5] &= ~(1 << (irq & 0x1F));
}

/**
 * @brief set the threshold
 * @param [in] threshold
 */
void PLIC_SetThreshold(uint32_t threshold)
{
    PLIC->context[0].THRESHOLD = threshold;
}

/**
 * @brief get the threshold
 * @return uint32_t 
 */
uint32_t PLIC_GetThreshold()
{
    return PLIC->context[0].THRESHOLD;
}

/**
 * @brief get the active interrupt
 * @return uint32_t 
 */
uint32_t PLIC_GetClaimIRQ()
{
    return PLIC->context[0].CLAIM;
}

/**
 * @brief complete the interrupt
 * @param [in] irq
 */
void PLIC_CompleteIRQ(uint32_t irq)
{
    PLIC->context[0].COMPLETE = irq;
}